﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Text;

using Ordinaire.Commerce.Data;
using Ordinaire.Data;

namespace Ordinaire.Commerce.Data
{
    [Table(Name = "InvoiceItems")]
    public class InvoiceItems<TInvoices> : ReferenceData<TInvoices, int, string>
        where TInvoices : Invoices
    {
        #region Variables

        /// <summary>
        /// Storage for association to table "Goods".
        /// </summary>
        protected EntityRef<Goods> goods = new EntityRef<Goods>();

        #endregion

        #region Data Overrides

        /// <summary>
        /// Get or set the entry unique identifier.
        /// </summary>
        [Column(IsPrimaryKey = true, IsDbGenerated = true, UpdateCheck = UpdateCheck.Never)]
        public override int Id
        {
            get { return base.Id; }
            set { base.Id = value; }
        }

        #endregion

        #region ReferenceData overrides

        /// <summary>
        /// Gets or sets the foreign id of the "Invoices" table..
        /// </summary>
        [Column(Name = "InvoiceId", DbType = "int NOT NULL", UpdateCheck = UpdateCheck.Never)]
        public override int ForeignId
        {
            get { return base.ForeignId; }
            set { base.ForeignId = value; }
        }

        /// <summary>
        /// Gets or sets the associated data from the "Invoices" table.
        /// </summary>
        [Association(IsForeignKey = true, ThisKey = "ForeignId", OtherKey = "Id", Storage = "foreign")]
        public override TInvoices Foreign
        {
            get { return base.Foreign; }
            set { base.Foreign = value; }
        }

        #endregion

        #region Columns

        /// <summary>
        /// Gets or sets the record id of related table "Goods".
        /// </summary>
        [Column(DbType = "int NULL", UpdateCheck = UpdateCheck.Never)]
        public virtual int? GoodId { get; set; }

        /// <summary>
        /// Holds the related invoice item for payment/exchange/refund.
        /// </summary>
        [Column(DbType = "int NULL", UpdateCheck = UpdateCheck.Never)]
        public virtual int? InvoiceItemId { get; set; }

        /// <summary>
        /// Gets or sets the amount of good purchased.
        /// </summary>
        [Column(DbType = "int NOT NULL DEFAULT(1)", UpdateCheck = UpdateCheck.Never)]
        public virtual int Quantity { get; set; }

        /// <summary>
        /// Gets or sets the measureable unit.
        /// </summary>
        [Column(DbType = "int NULL", CanBeNull = true, UpdateCheck = UpdateCheck.Never)]
        public virtual int? MeasureUnitId { get; set; }

        /// <summary>
        /// Gets or sets the discount amount given for this purchase.
        /// </summary>
        [Column(DbType = "decimal(18,5) NOT NULL DEFAULT(0)", UpdateCheck = UpdateCheck.Never)]
        public virtual decimal Discount { get; set; }

        /// <summary>
        /// Gets or sets the tax amount charged for this purchase.
        /// </summary>
        [Column(DbType = "decimal(18,5) NOT NULL DEFAULT(0)", UpdateCheck = UpdateCheck.Never)]
        public virtual decimal Tax { get; set; }

        /// <summary>
        /// Gets or sets the value of current purchase item.
        /// </summary>
        [Column(DbType = "decimal(18,5) NOT NULL DEFAULT(0)", UpdateCheck = UpdateCheck.Never)]
        public virtual decimal Value { get; set; }

        /// <summary>
        /// Gets or sets the payment date.
        /// </summary>
        [Column(DbType = "date NULL", UpdateCheck = UpdateCheck.Never)]
        public virtual DateTime? Date { get; set; }

        #endregion

        #region Association

        /// <summary>
        /// Returns the corresponding data from "Goods" table.
        /// </summary>
        [Association(ThisKey = "GoodId", OtherKey = "Id", Storage = "goods")]
        public virtual Goods Goods
        {
            get { return goods.Entity; }
        }

        #endregion

        #region IAudit overrides

        /// <summary>
        /// Get or set the username who created this entry.
        /// </summary>
        [Column(DbType = "nvarchar(10) NOT NULL", UpdateCheck = UpdateCheck.Never)]
        public override string CreatedBy
        {
            get { return base.CreatedBy; }
            set { base.CreatedBy = value; }
        }

        /// <summary>
        /// Get or set the date when the entry was first created.
        /// </summary>
        [Column(DbType = "datetime NOT NULL", UpdateCheck = UpdateCheck.Never)]
        public override DateTime? CreateDate
        {
            get { return base.CreateDate; }
            set { base.CreateDate = value; }
        }

        /// <summary>
        /// Get or set the username who last updated this entry.
        /// </summary>
        [Column(DbType = "nvarchar(10) NULL", UpdateCheck = UpdateCheck.Never)]
        public override string UpdatedBy
        {
            get { return base.UpdatedBy; }
            set { base.UpdatedBy = value; }
        }

        /// <summary>
        /// Get or set the date when the entry was last updated.
        /// </summary>
        [Column(DbType = "datetime NULL", UpdateCheck = UpdateCheck.Never)]
        public override DateTime? UpdateDate
        {
            get { return base.UpdateDate; }
            set { base.UpdateDate = value; }
        }

        #endregion
    }

    /// <summary>
    /// Contains list of extension methods for Ordinaire.Commerce.Data.InvoiceItems.
    /// </summary>
    public static class InvoiceItemsExtension
    {
        /// <summary>
        /// Converts the specified collection of InvoiceItems data to list of Ordinaire.Commerce.InvoiceDetail instance.
        /// </summary>
        /// <param name="dataArray">array of data to convert</param>
        /// <returns>list of Ordinaire.Commerce.InvoiceDetail instance representing the data</returns>
        public static List<InvoiceDetail> ToInvoiceDetails<TInvoices>(this ICollection<InvoiceItems<TInvoices>> dataArray)
            where TInvoices : Invoices
        {
            if (dataArray == null || dataArray.Count == 0)
            {
                return new List<InvoiceDetail>();
            }

            return dataArray.AsEnumerable().Select(d => d.ToInvoiceDetail<TInvoices>()).ToList();
        }

        /// <summary>
        /// Converts the specified PurchaseItems data to Ordinaire.Commerce.InvoiceDetail instance.
        /// </summary>
        /// <param name="data">the data to convert</param>
        /// <returns>Ordinaire.Commerce.InvoiceDetail instance representing the data</returns>
        public static InvoiceDetail ToInvoiceDetail<TInvoices>(this InvoiceItems<TInvoices> data)
            where TInvoices : Invoices
        {
            if (data == null)
            {
                return null;
            }

            return new InvoiceDetail()
            {
                Id       = data.Id,
                Good     = data.Goods.ToGood(),
                Quantity = (decimal) data.Quantity,
                Discount = data.Discount,
                Tax      = data.Tax
            };
        }
    }
}
